﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using daStaticAnalyser.Analysers;
using daStaticAnalyser;
using daBase.Analyser;
using daBase.Objects.AnalysisErrors;
using daSyntaxAnalyser;
using daSyntaxAnalyser.SyntaxTree;

namespace DifferentAnalizers
{
    /// <summary>
    /// Анализатор - длина идентификатора
    /// </summary>
    [AnalyserDefaultSettings("Длина идентификатора.", "Неправильный идентификатор (некорректная длина)!", 10, "Данный идентификатор имеет недопустимую длину. Переименуйте его или добавьте в исключения.")]
    public class IdLengthAnalyser : IdAnalyser
    {
        // Регулярное выражение
        private string regex;

        /// <summary>
        /// Набор допустимых длин
        /// </summary>
        [Category("Особые")]
        [DisplayName("Длина")]
        [Description("Все допустимые длины для идентификатора.")]
        public List<LengthConfig> Lengths { get { return (settings as IdLengthSettings).Lengths; } set { (settings as IdLengthSettings).Lengths = value; Change(); } }

        /// <summary>
        /// "Хорошие" идентификаторы (исключаются из анализа)
        /// </summary>
        [Category("Особые")]
        [DisplayName("Стандартные")]
        [Description("Стандартные идентификаторы, которые не будут обнаружены при анализе")]
        public List<GoodId> StdIdes { get { return (settings as IdLengthSettings).StandartIds; } set { (settings as IdLengthSettings).StandartIds = value; } }

        /// <summary>
        /// Изменение свойств
        /// </summary>
        protected override void CheckChanges()
        {
            if ((settings as IdLengthSettings).Lengths.Count < 1) settings.Enabled = false;
            MakeRegexes();
        }

        /// <summary>
        /// Инициализация
        /// </summary>
        protected override void Init()
        {
            if (settings == null)
                settings = new IdLengthSettings();
            (settings as IdLengthSettings).Lengths.Add(new LengthConfig(1, 1));
            (settings as IdLengthSettings).Lengths.Add(new LengthConfig(4, 0));
            base.Init();
            MakeRegexes();
        }

        /// <summary>
        /// Создание регулярное выражение по интервалу
        /// </summary>
        /// <param name="cfg">интервал</param>
        /// <returns>регулярное выражение</returns>
        private string MakeRegex(LengthConfig cfg)
        {
            return (cfg.From != cfg.To) ? string.Format(".{{{0},{1}}}", cfg.From, ((cfg.To == 0) ? "" : cfg.To.ToString())) : string.Format(".{{{0}}}", cfg.From);
        }

        /// <summary>
        /// Создание регулярного выражения
        /// </summary>
        private void MakeRegexes()
        {
            int l = (settings as IdLengthSettings).Lengths.Count;
            regex = (l > 0) ? MakeRegex((settings as IdLengthSettings).Lengths[0]) : string.Empty;
            if (l > 0)
            {
                for (int i = 1; i < l; i++)
                    regex = string.Format("{0}|{1}", regex, MakeRegex((settings as IdLengthSettings).Lengths[i]));
                regex = string.Format("^({0})$", regex);
            }
        }

        /// <summary>
        /// Собственно анализ
        /// </summary>
        /// <param name="e">параметр анализа</param>
        protected override void DoAnalyse(SyntaxTreeArgs e)
        {
            if (e.Element is IdElement)
            {
                TokenInfo Id = (e.Element as IdElement).Id;
                if ((Id != null) && (Id.Token == DelphiTokens.Id) && !(settings as IdLengthSettings).StandartIds.Contains(new GoodId(Id.Text)) && !Regex.IsMatch(Id.Text, regex) && (!(settings as IdLengthSettings).DfmIsGood || !Id.DfmIds.Contains(Id.Text.ToLower())))
                    AddError(Id, e.Element.ToString());
            }
        }
    }
}
